﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using My.Common.Error;
using NCLCustomerManagement.DataAccess;
using My.DataAccess.Core;
using My.Pattern.Builder;

namespace NCLCustomerManagement.BusinessLogic
{
    public abstract class BaseBC : IBaseBC
    {
        public IErrorLog ErrorLog { get; set; }
        public IErrorBuilder ErrorBuilder { get; set; }

        #region abstract Methods

        public abstract IBaseRepository<DTO> GetRepository<DTO>() where DTO : class;

        #endregion

        #region Insert Methods

        public void Insert<DTO>(List<DTO> dtos) where DTO : class
        {
            if (dtos != null && dtos.Any())
            {
                foreach (var dto in dtos)
                {
                    Insert<DTO>(dto);
                }
            }
        }

        public DTO Insert<DTO>(DTO dto) where DTO : class
        {
            try
            {
                ValidateBeforeInsert(dto);
                return CoreInsert<DTO>(dto);
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
                throw ex;
            }
        }

        protected virtual void ValidateBeforeInsert<DTO>(DTO dto)
        {
        }

        /// <summary>
        /// This function will be sent request to repository for inserting data. Howver, if there is any special business, 
        /// this methods could be overrided at individual BC file for its purpose
        /// </summary>
        /// <typeparam name="DTO"></typeparam>
        /// <param name="dto"></param>
        /// <returns></returns>
        protected virtual DTO CoreInsert<DTO>(DTO dto) where DTO : class
        {
            var repository = GetRepository<DTO>();
            return repository.Insert(dto);
        }

        #endregion

        #region Update Methods

        public DTO Update<DTO>(DTO dto) where DTO : class
        {
            try
            {
                ValidateBeforeUpdate(dto);
                return CoreUpdate<DTO>(dto);
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
                throw ex;
            }
        }

        protected virtual void ValidateBeforeUpdate<DTO>(DTO dto)
        {

        }

        protected virtual DTO CoreUpdate<DTO>(DTO dto) where DTO : class
        {
            var repository = GetRepository<DTO>();
            return repository.Update(dto);
        }

        #endregion

        #region Delete Methods

        public DTO Delete<DTO>(DTO dto) where DTO : class
        {
            try
            {
                ValidateBeforeDelete(dto);
                CoreDelete<DTO>(dto);
                return dto;
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
                throw ex;
            }
        }

        protected virtual void ValidateBeforeDelete<DTO>(DTO dto)
        {
        }

        /// <summary>
        /// This function will be sent request to repository for inserting data. Howver, if there is any special business, 
        /// this methods could be overrided at individual BC file for its purpose
        /// </summary>
        /// <typeparam name="DTO"></typeparam>
        /// <param name="dto"></param>
        /// <returns></returns>
        protected virtual void CoreDelete<DTO>(DTO dto) where DTO : class
        {
            var repository = GetRepository<DTO>();
            repository.Delete(dto);
        }

        #endregion

        #region Get Methods

        public DTO GetBy<DTO>(int dtoId) where DTO : class
        {
            try
            {
                var repository = GetRepository<DTO>();
                return repository.GetById(dtoId);
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
                throw ex;
            }
        }

        public List<DTO> GetAll<DTO>() where DTO : class
        {
            try
            {
                var repository = GetRepository<DTO>();
                return repository.GetAll();
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
                throw ex;
            }
        }

        #endregion
    }
}
